home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
Dev
/
Oberon
/
source
/
OC
/
OCE.mod
< prev
next >
Wrap
Text File
|
1995-07-02
|
51KB
|
1,566 lines
(*************************************************************************
$RCSfile: OCE.mod $
Description: Code selection for expressions
Created by: fjc (Frank Copeland)
$Revision: 5.22 $
$Author: fjc $
$Date: 1995/07/02 16:52:04 $
Copyright © 1990-1993, ETH Zuerich
Copyright © 1993-1995, Frank Copeland
This module forms part of the OC program
See OC.doc for conditions of use and distribution
Log entries are at the end of the file.
*************************************************************************)
<* STANDARD- *> <* MAIN- *> <*$ LongVars+ *>
MODULE OCE;
IMPORT SYS := SYSTEM, OCM, OCS, OCT, OCC, OCI;
(* --- Local declarations --------------------------------------------- *)
CONST
(* Symbols *)
null = OCS.null; times = OCS.times; slash = OCS.slash; div = OCS.div;
mod = OCS.mod; and = OCS.and; plus = OCS.plus; minus = OCS.minus;
or = OCS.or; eql = OCS.eql; neq = OCS.neq; lss = OCS.lss;
leq = OCS.leq; gtr = OCS.gtr; geq = OCS.geq; not = OCS.not;
(* object modes *)
Var = OCM.Var; VarX = OCM.VarX; Ind = OCM.Ind; IndX = OCM.IndX;
RegI = OCM.RegI; RegX = OCM.RegX; Lab = OCM.Lab; LabI = OCM.LabI;
Con = OCM.Con; Push = OCM.Push; Pop = OCM.Pop; Coc = OCM.Coc;
Reg = OCM.Reg; Fld = OCM.Fld; Typ = OCM.Typ; Abs = OCM.Abs;
XProc = OCM.XProc; RList = OCM.RList;
(* System flags *)
OberonFlag = OCM.OberonFlag; M2Flag = OCM.M2Flag; CFlag = OCM.CFlag;
BCPLFlag = OCM.BCPLFlag; AsmFlag = OCM.AsmFlag;
(* structure forms *)
Undef = OCT.Undef; Byte = OCT.Byte; Bool = OCT.Bool; Char = OCT.Char;
SInt = OCT.SInt; Int = OCT.Int; LInt = OCT.LInt; Real = OCT.Real;
LReal = OCT.LReal; Set = OCT.Set; String = OCT.String;
NilTyp = OCT.NilTyp; NoTyp = OCT.NoTyp; Pointer = OCT.Pointer;
ProcTyp = OCT.ProcTyp; Array = OCT.Array; DynArr = OCT.DynArr;
Record = OCT.Record; PtrTyp = OCT.PtrTyp; AdrTyp = OCT.AdrTyp;
BPtrTyp = OCT.BPtrTyp; BSet = OCT.BSet; WSet = OCT.WSet;
Word = OCT.Word; Longword = OCT.Longword; TagTyp = OCT.TagTyp;
intSet = {SInt, Int, LInt};
realSet = {Real, LReal};
setSet = {BSet, WSet, Set};
ptrSet = {Pointer, PtrTyp, AdrTyp, BPtrTyp};
uptrSet = {AdrTyp, BPtrTyp};
allSet = {0 .. 31};
adrSet = {LInt, Pointer, PtrTyp, AdrTyp, Longword};
(* CPU Registers *)
D0 = 0; D1 = 1; D7 = 7; A0 = 8; A1 = 9; A3 = 11; A4 = 12; A5 = 13;
A6 = 14; A7 = 15; BP = A4; FP = A5; SP = A7;
DataRegs = {D0 .. D7};
AdrRegs = {A0 .. A7};
(* Data sizes *)
B = 1; W = 2; L = 4;
(* mathffp.library function offsets *)
SPFix = -30; SPFlt = -36; SPCmp = -42; SPTst = -48; SPAbs = -54;
SPNeg = -60; SPAdd = -66; SPSub = -72; SPMul = -78; SPDiv = -84;
SPFloor = -90; SPCeil = -96;
VAR
log : LONGINT; (* side effect of mant () *)
(* --- Procedure declarations ------------------------------------------- *)
PROCEDURE^ Op *
(op : INTEGER; VAR lhs, rhs : OCT.Item; freeRegs : BOOLEAN);
(*------------------------------------*)
PROCEDURE mant (x : LONGINT) : LONGINT; (* x DIV 2 ^ log *)
BEGIN (* mant *)
log := 0;
IF x > 0 THEN WHILE ~ODD (x) DO x := x DIV 2; INC (log) END END;
RETURN x
END mant;
(*------------------------------------*)
PROCEDURE MultiplyInts (
VAR lhs, rhs : OCT.Item; size : LONGINT; freeRegs : BOOLEAN);
VAR R : OCC.RegState; x : OCT.Item;
BEGIN (* MultiplyInts *)
IF (lhs.mode = Con) & (mant (lhs.a0) = 1) THEN
IF log = 1 THEN
OCI.Load (rhs); OCC.PutF5 (OCC.ADD, size, rhs, rhs)
ELSIF log # 0 THEN
lhs.a0 := log; lhs.typ := OCT.sinttyp;
IF log > 8 THEN OCI.Load (lhs) END;
OCI.Load (rhs); OCC.Shift (OCC.ASL, size, lhs, rhs);
IF log > 8 THEN OCC.FreeReg (lhs) END;
END;
lhs := rhs; rhs.mode := Undef
ELSIF (rhs.mode = Con) & (mant (rhs.a0) = 1) THEN
IF log = 1 THEN
OCI.Load (lhs); OCC.PutF5 (OCC.ADD, size, lhs, lhs)
ELSIF log # 0 THEN
rhs.a0 := log; rhs.typ := OCT.sinttyp;
IF log > 8 THEN OCI.Load (rhs) END;
OCI.Load (lhs); OCC.Shift (OCC.ASL, size, rhs, lhs)
END
ELSE
IF size = L THEN
OCC.LoadRegParams2 (R, lhs, rhs);
OCC.CallKernel (OCC.kMul32);
OCC.RestoreRegisters (R, lhs);
ELSE
IF lhs.mode = Con THEN x := lhs; lhs := rhs; rhs := x END;
OCI.Load (lhs);
IF size = B THEN
OCI.EXT (W, lhs.a0);
IF rhs.mode # Con THEN OCI.Load (rhs); OCI.EXT (W, rhs.a0) END;
END;
OCC.PutF2 (OCC.MULS, rhs, lhs.a0);
IF OCS.pragma [OCS.ovflChk] THEN
OCC.GetDReg (x, NIL); OCC.Move (size, lhs, x);
IF size = B THEN OCI.EXT (W, x.a0) END; OCI.EXT (L, x.a0);
OCI.CMP (L, lhs, x);
OCC.TrapCC (OCC.RangeCheck, OCC.NE)
END
END
END;
IF freeRegs THEN OCI.Unload (rhs) END
END MultiplyInts;
(*------------------------------------*)
PROCEDURE DivideInts (
VAR lhs, rhs : OCT.Item; size : LONGINT; freeRegs : BOOLEAN);
VAR R : OCC.RegState;
BEGIN (* DivideInts *)
IF (rhs.mode = Con) & (mant (rhs.a0) = 1) THEN
rhs.a0 := log; rhs.typ := OCT.sinttyp;
IF log > 8 THEN OCI.Load (rhs) END;
OCI.Load (lhs);
OCC.Shift (OCC.ASR, size, rhs, lhs);
ELSE
IF size = OCM.LIntSize THEN
OCC.LoadRegParams2 (R, lhs, rhs);
OCC.CallKernel (OCC.kDiv32);
OCC.RestoreRegisters (R, lhs);
ELSE
OCI.Load (lhs);
IF lhs.typ^.form = OCT.SInt THEN OCI.EXT (W, lhs.a0) END;
OCI.EXT (L, lhs.a0);
IF rhs.typ^.form = OCT.SInt THEN
OCI.Load (rhs); OCI.EXT (W, rhs.a0)
END;
OCC.PutF2 (OCC.DIVS, rhs, lhs.a0);
(*IF OCS.pragma [OCS.ovflChk] THEN OCC.OutOp0 (TRAPV) END;*)
END
END;
IF freeRegs THEN OCI.Unload (rhs) END;
END DivideInts;
(*------------------------------------*)
PROCEDURE ModulusInts (
VAR lhs, rhs : OCT.Item; size : LONGINT; freeRegs : BOOLEAN);
VAR R : OCC.RegState;
BEGIN (* ModulusInts *)
IF (rhs.mode = Con) & (mant (rhs.a0) = 1) THEN
rhs.a0 := ASH (1, log) - 1; OCI.Load (lhs);
OCC.PutF6 (OCC.ANDI, size, rhs, lhs)
ELSE
IF size = OCM.LIntSize THEN
OCC.LoadRegParams2 (R, lhs, rhs);
OCC.CallKernel (OCC.kDiv32);
OCC.PutWord (0C141H); (* EXG D0,D1 *)
OCC.RestoreRegisters (R, lhs)
ELSE
OCI.Load (lhs);
IF lhs.typ^.form = OCT.SInt THEN OCI.EXT (W, lhs.a0) END;
OCI.EXT (L, lhs.a0);
IF rhs.typ^.form = OCT.SInt THEN
OCI.Load (rhs); OCI.EXT (L, rhs.a0)
END;
OCC.PutF2 (OCC.DIVS, rhs, lhs.a0);
OCC.PutWord (OCC.SWAP + lhs.a0)
END
END;
IF freeRegs THEN OCI.Unload (rhs) END
END ModulusInts;
(*------------------------------------*)
PROCEDURE ConvertInts * (VAR x : OCT.Item; typ : OCT.Struct);
BEGIN (* ConvertInts *)
IF x.mode # Con THEN
OCI.Load (x);
IF (typ.form = LInt) & (x.typ.form = SInt) THEN OCI.EXT (W, x.a0) END;
OCI.EXT (typ.size, x.a0)
END;
x.typ := typ
END ConvertInts;
(*------------------------------------*)
PROCEDURE RealMath (op : INTEGER; VAR lhs, rhs : OCT.Item);
VAR proc : INTEGER; R : OCC.RegState;
BEGIN (* RealMath *)
OCC.LoadRegParams2 (R, lhs, rhs);
CASE op OF
times : proc := OCC.kSPMul | slash : proc := OCC.kSPDiv |
plus : proc := OCC.kSPAdd | minus : proc := OCC.kSPSub
ELSE
OCS.Mark (1009); OCS.Mark (op)
END;
OCC.CallKernel (proc); OCC.RestoreRegisters (R, lhs)
END RealMath;
(*------------------------------------*)
PROCEDURE CmpReals (VAR lhs, rhs : OCT.Item);
VAR R : OCC.RegState; proc : INTEGER;
BEGIN (* CmpReals *)
IF (rhs.mode = Con) & (rhs.a0 = 0) THEN
OCC.LoadRegParams1 (R, lhs); proc := OCC.kSPTst
ELSE
OCC.LoadRegParams2 (R, lhs, rhs); proc := OCC.kSPCmp
END;
OCC.CallKernel (proc); OCC.RestoreRegisters (R, lhs)
END CmpReals;
(*------------------------------------*)
PROCEDURE ConvertReals (VAR x : OCT.Item; typ : OCT.Struct);
VAR r0 : OCT.Item; R : OCC.RegState; f : INTEGER; real : REAL;
BEGIN (* ConvertReals *)
f := x.typ.form;
IF f IN intSet THEN
IF x.mode = Con THEN
real := x.a0; x.a0 := SYS.VAL (LONGINT, real)
ELSE
r0.mode := Reg; r0.a0 := D0;
OCC.LoadRegParams1 (R, x);
IF f = SInt THEN OCI.EXT (W, r0.a0); f := Int END;
IF f = Int THEN OCI.EXT (L, r0.a0) END;
OCC.CallKernel (OCC.kSPFlt);
OCC.RestoreRegisters (R, x)
END
END;
x.typ := typ
END ConvertReals;
(*------------------------------------*)
PROCEDURE NegReal (VAR x : OCT.Item);
VAR R : OCC.RegState;
BEGIN (* NegReal *)
OCC.LoadRegParams1 (R, x);
OCC.CallKernel (OCC.kSPNeg);
OCC.RestoreRegisters (R, x)
END NegReal;
(*------------------------------------*)
PROCEDURE loadB (VAR x : OCT.Item); (* Coc-Mode *)
VAR op, L0 : LONGINT;
BEGIN (* loadB *)
IF ((x.a1 = 0) & (x.a2 = 0)) OR (x.a0 IN {OCC.T, OCC.F}) THEN
op := OCC.Scc + (x.a0 * 100H);
OCC.GetDReg (x, NIL); OCC.PutF3 (op, x) (* Scc Dn *)
ELSE
op := OCC.Bcc + (OCC.invertedCC (x.a0) * 100H);
OCC.PutWord (op); OCC.PutWord (x.a2); (* Bcc 1$ *)
L0 := OCC.pc - 2; OCC.FixLink (x.a1);
OCC.GetDReg (x, NIL); OCC.PutF3 (OCC.ST, x); (* ST Dn *)
OCC.PutWord (6002H); (* BRA 2$ *)
OCC.FixLink (L0); OCC.PutF3 (OCC.SF, x); (* 1$ SF Dn *)
END (* 2$ *)
END loadB;
(*------------------------------------*)
PROCEDURE setCC * (VAR x: OCT.Item; cc : LONGINT);
BEGIN (* setCC *)
x.typ := OCT.booltyp; x.mode := Coc; x.a0 := cc; x.a1 := 0; x.a2 := 0
END setCC;
(*------------------------------------*)
PROCEDURE cmp (VAR lhs, rhs : OCT.Item; freeX : BOOLEAN);
VAR size : LONGINT;
BEGIN (* cmp *)
size := lhs.typ.size; IF size > L THEN size := L END;
IF rhs.mode = Con THEN
IF lhs.mode = Con THEN OCI.Load (lhs)
ELSIF lhs.mode = Coc THEN loadB (lhs)
END;
IF rhs.a0 = 0 THEN OCC.PutF1 (OCC.TST, size, lhs)
ELSE OCC.PutF6 (OCC.CMPI, size, rhs, lhs)
END
ELSE
IF lhs.mode = Coc THEN loadB (lhs)
ELSE OCI.Load (lhs)
END;
OCC.PutF5 (OCC.CMP, size, rhs, lhs);
END;
IF freeX THEN OCI.Unload (lhs) END
END cmp;
(*------------------------------------*)
PROCEDURE test (VAR x : OCT.Item);
BEGIN (* test *)
OCC.PutF1 (OCC.TST, x.typ.size, x); OCI.Unload (x); setCC (x, OCC.NE)
END test;
(*------------------------------------*)
PROCEDURE SetIntType * (VAR x : OCT.Item);
VAR v : LONGINT;
BEGIN (* SetIntType *)
v := x.a0;
IF (LONG (OCM.MinSInt) <= v) & (v <= LONG (OCM.MaxSInt)) THEN
x.typ := OCT.sinttyp
ELSIF (LONG (OCM.MinInt) <= v) & (v <= LONG (OCM.MaxInt)) THEN
x.typ := OCT.inttyp
ELSE
x.typ := OCT.linttyp
END;
END SetIntType;
(*------------------------------------*)
PROCEDURE SetSetType (VAR x : OCT.Item);
VAR s : SET;
BEGIN (* SetSetType *)
s := SYS.VAL (SET, x.a0);
IF (s - {OCM.MinSet .. OCM.MaxBSet}) = {} THEN
x.typ := OCT.bsettyp
ELSIF (s - {OCM.MinSet .. OCM.MaxWSet}) = {} THEN
x.typ := OCT.wsettyp
ELSE
x.typ := OCT.settyp
END
END SetSetType;
(*------------------------------------*)
PROCEDURE AssReal * (VAR x : OCT.Item; y : REAL);
BEGIN (* AssReal *)
SYS.PUT (SYS.ADR (x.a0), y)
END AssReal;
(*------------------------------------*)
PROCEDURE AssLReal * (VAR x : OCT.Item; y : LONGREAL);
BEGIN (* AssLReal *)
SYS.PUT (SYS.ADR (x.a0), y)
END AssLReal;
(*------------------------------------*)
PROCEDURE Index * (VAR x, y : OCT.Item);
VAR
f, m, r : INTEGER; L0, i, n : LONGINT;
eltyp : OCT.Struct; t1, t2 : OCT.Item;
desc : OCT.Desc; wordSize, calcSize, ovflChk : BOOLEAN;
BEGIN (* Index *)
ovflChk := OCS.pragma [OCS.ovflChk]; OCS.pragma [OCS.ovflChk] := FALSE;
f := y.typ.form;
IF ~(f IN intSet) THEN OCS.Mark (80); y.typ := OCT.inttyp END;
IF x.typ = NIL THEN OCS.Mark (80); HALT (80) END;
IF x.typ.form = Array THEN
eltyp := x.typ.BaseTyp; n := x.typ.n;
wordSize := (x.typ.size <= 32767);
IF eltyp = NIL THEN OCS.Mark (81); HALT (81) END;
IF y.mode = Con THEN
IF (0 <= y.a0) & (y.a0 < n) THEN i := y.a0 * eltyp.size
ELSE OCS.Mark (81); i := 0
END;
IF x.mode = Var THEN INC (x.a0, i)
ELSIF x.mode = RegI THEN INC (x.a1, i)
ELSE OCI.LoadAdr (x); x.a1 := i
END;
IF x.obj # OCC.wasderef THEN x.obj := NIL END;
ELSE
OCI.Load (y);
IF f = SInt THEN
OCI.EXT (W, y.a0); y.typ := OCT.inttyp; f := Int
END;
IF (n > 32767) & (f = Int) THEN
OCI.EXT (L, y.a0); y.typ := OCT.linttyp; f := LInt
END;
IF OCS.pragma [OCS.indexChk] THEN (* t1 = bound descr *)
t1.mode := Con; t1.a0 := n - 1;
IF f = Int THEN t1.typ := OCT.inttyp; OCC.PutCHK (t1, y.a0)
ELSE
OCC.PutF1 (OCC.TST, L, y); (* TST.L Dy *)
L0 := OCC.pc; OCC.PutWord (6B00H); (* BMI.S 1$ *)
t1.typ := OCT.linttyp;
cmp (y, t1, FALSE); (* CMP.L #t1,Dy *)
OCC.TrapLink (OCC.IndexCheck, OCC.GT, L0);
(* BLE.S 2$ *)
(* 1$ TRAP #IndexCheck *)
END (* 2$ *)
END;
m := x.mode;
IF m = Var THEN
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (t1, x.obj)
ELSE
OCC.GetAReg (t1, x.obj); t2 := x;
OCC.PutF2 (OCC.LEA, t2, t1.a0); OCI.Unload (t2)
END;
x.mode := RegX; x.a0 := t1.a0; x.a1 := 0; x.a2 := y.a0;
x.wordIndex := wordSize; calcSize := eltyp.size > 1
ELSIF m = Ind THEN
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (t1, x.obj)
ELSE
OCC.GetAReg (t1, x.obj); t2 := x; t2.mode := Var;
OCC.Move (L, t2, t1); OCI.Unload (t2)
END;
x.mode := RegX; x.a0 := t1.a0; x.a2 := y.a0;
x.wordIndex := wordSize; calcSize := eltyp.size > 1
ELSIF m = RegI THEN
x.mode := RegX; x.wordIndex := wordSize; x.a2 := y.a0;
calcSize := eltyp.size > 1;
ELSIF m IN {VarX, IndX, RegX} THEN
IF eltyp.size > 1 THEN
t1.mode := Con; t1.a0 := eltyp.size;
IF x.wordIndex THEN t1.typ := OCT.inttyp
ELSE t1.typ := OCT.linttyp
END;
Op (times, y, t1, FALSE)
END;
t1 := y; y.mode := Reg; y.a0 := x.a2;
IF x.wordIndex THEN y.typ := OCT.inttyp
ELSE y.typ := OCT.linttyp
END;
Op (plus, y, t1, TRUE);
calcSize := FALSE;
ELSE OCS.Mark (322)
END;
IF x.obj # OCC.wasderef THEN x.obj := NIL END;
IF calcSize THEN
t1.mode := Con; t1.a0 := eltyp.size;
IF x.wordIndex THEN t1.typ := OCT.inttyp
ELSE t1.typ := OCT.linttyp
END;
Op (times, y, t1, FALSE)
END
END; (* ELSE *)
x.typ := eltyp
ELSIF x.typ.form = DynArr THEN
IF f # LInt THEN ConvertInts (y, OCT.linttyp)
ELSIF y.mode # Con THEN OCI.Load (y)
END;
IF OCS.pragma [OCS.indexChk] THEN
IF (y.mode = Con) & (y.a0 < 0) THEN OCS.Mark (81)
ELSE
(* t1 = bound descr *)
OCI.DescItem (t1, x.desc, x.typ.adr);
IF y.mode # Con THEN
OCC.PutF1 (OCC.TST, L, y); (* TST.L y *)
L0 := OCC.pc; OCC.PutWord (6B00H); (* BMI.S 1$ *)
cmp (y, t1, FALSE); (* CMP.L t1,Dy *)
OCC.TrapLink (OCC.IndexCheck, OCC.GE, L0);
(* BLT.S 2$ *)
(* 1$ TRAP #IndexCheck *)
(* 2$ *)
ELSE
cmp (t1, y, FALSE); (* CMP.L y,t1 *)
OCC.TrapCC (OCC.IndexCheck, OCC.LE); (* BGT.S 1$ *)
(* TRAP #IndexCheck *)
(* 1$ *)
END;
OCI.UpdateDesc (t1, x.typ.adr)
END (* ELSE *)
END; (* IF *)
IF x.mode IN {Var, Ind} THEN
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (t1, x.obj)
ELSE
OCC.GetAReg (t1, x.obj); t2 := x; t2.mode := Var;
OCC.Move (L, t2, t1); OCI.Unload (t2)
END;
IF y.mode = Con THEN
x.mode := RegI; x.a0 := t1.a0; x.a1 := y.a0
ELSE
x.mode := RegX; x.a0 := t1.a0; x.a2 := y.a0;
x.wordIndex := FALSE
END
ELSIF x.mode = RegI THEN (* Dereferenced ptr *)
IF y.mode = Con THEN x.a1 := y.a0
ELSE x.mode := RegX; x.a2 := y.a0; x.wordIndex := FALSE
END
ELSIF x.mode IN {IndX, RegX} THEN (* Indexed open array *)
IF ~OCS.pragma [OCS.indexChk] THEN (* t1 = bound descr *)
OCI.DescItem (t1, x.desc, x.typ.adr);
END;
t2.mode := Reg; t2.a0 := x.a2; t2.typ := OCT.linttyp;
Op (times, t2, t1, FALSE); Op (plus, t2, y, TRUE); y := t2;
OCI.UpdateDesc (t1, x.typ.adr)
ELSE OCS.Mark (322)
END;
IF x.obj # OCC.wasderef THEN x.obj := NIL END;
x.typ := x.typ.BaseTyp;
IF x.typ # NIL THEN
IF (x.typ.form # DynArr) THEN
IF x.typ.size > 1 THEN
t1.mode := Con; t1.a0 := x.typ.size; SetIntType (t1);
Op (times, y, t1, FALSE)
END;
IF y.mode = Con THEN x.a1 := y.a0 END
ELSIF (y.mode = Con) & (y.a0 # 0) THEN
OCI.Load (y); x.a1 := 0; x.a2 := y.a0; x.wordIndex := FALSE;
IF x.mode = Ind THEN x.mode := IndX
ELSIF x.mode = RegI THEN x.mode := RegX
ELSE OCS.Mark (322)
END
END
END
ELSE
OCS.Mark (82)
END;
OCS.pragma [OCS.ovflChk] := ovflChk
END Index;
(*------------------------------------*)
PROCEDURE Field * (VAR x : OCT.Item; y : OCT.Object);
VAR t1, t2 : OCT.Item;
BEGIN (* Field *)
IF x.mode = Var THEN
INC (x.a0, y.a0)
ELSIF x.mode = Ind THEN
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (t1, x.obj)
ELSE
OCC.GetAReg (t1, x.obj); t2 := x; t2.mode := Var;
OCC.Move (L, t2, t1); OCI.Unload (t2)
END;
x.mode := RegI; x.a0 := t1.a0; INC (x.a1, y.a0)
ELSIF x.mode = RegI THEN
INC (x.a1, y.a0)
ELSE
OCI.LoadAdr (x); x.mode := RegI; x.a1 := y.a0
END;
x.typ := y.typ; x.obj := NIL;
IF x.lev < 0 THEN x.rdOnly := x.rdOnly OR (y.visible = OCT.RdOnly) END
END Field;
(*------------------------------------*)
PROCEDURE DeRef * (VAR x : OCT.Item; load : BOOLEAN);
VAR
y, z : OCT.Item; flg : INTEGER; desc : OCT.Desc; freeY : BOOLEAN;
btyp : OCT.Struct;
BEGIN (* DeRef *)
IF (x.mode <= RegX) & (x.typ.form = Pointer) THEN
OCI.UnloadDesc (x); flg := x.typ.sysflg; btyp := x.typ.BaseTyp;
IF (flg = OberonFlag) & (btyp # NIL) & (btyp.form = DynArr)
THEN
desc := x.desc; IF desc = NIL THEN NEW (desc) END;
desc.lev := x.lev; desc.mode := x.mode; desc.a0 := x.a0;
desc.a1 := x.a1; desc.a2 := x.a2;
freeY := ~(desc.mode IN {VarX, IndX, RegI, RegX})
ELSE
desc := NIL; freeY := TRUE
END;
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (x, x.obj); x.desc := desc; x.mode := RegI
ELSE
IF flg = BCPLFlag THEN
y := x; y.obj := NIL; OCC.GetDReg (z, NIL);
OCC.Move (L, y, z); OCI.Unload (y); (* MOVE.L x,Dm *)
IF OCS.pragma [OCS.nilChk] THEN OCC.TrapCC (OCC.NilCheck, OCC.EQ)
END;
OCC.PutF5 (OCC.ADD, L, z, z); (* ADD.L Dm, Dm *)
OCC.PutF5 (OCC.ADD, L, z, z); (* ADD.L Dm, Dm *)
OCC.GetAReg (x, x.obj); OCC.Move (L, z, x); (* MOVEA.L Dm,An *)
OCI.Unload (z); x.mode := RegI
ELSE
y.mode := Undef; x.desc := desc;
IF ~load & (x.mode = Var) THEN
y := x;
IF OCS.pragma [OCS.nilChk] THEN
OCC.PutF1 (OCC.TST, L, y); (* TST.L x *)
OCC.TrapCC (OCC.NilCheck, OCC.EQ);
END;
x.mode := Ind
ELSE
y := x; y.obj := NIL; y.typ := OCT.ptrtyp; OCC.GetAReg (x, x.obj);
IF OCS.pragma [OCS.nilChk] THEN
OCC.GetDReg (z, NIL); OCC.Move (L, y, z); (* MOVE.L x,Dn *)
OCC.TrapCC (OCC.NilCheck, OCC.EQ);
OCC.Move (L, z, x); OCI.Unload (z) (* MOVEA.L Dn, An *)
ELSE
OCC.Move (L, y, x); (* MOVEA.L x, An *)
END;
IF freeY THEN OCI.Unload (y) END; x.mode := RegI
END
END
END;
x.typ := x.typ.BaseTyp; x.obj := OCC.wasderef; x.rdOnly := FALSE;
x.a2 := 0
ELSE
OCS.Mark (84)
END;
x.a1 := 0
END DeRef;
(*------------------------------------*)
PROCEDURE TypTest * (VAR x, y : OCT.Item; test : BOOLEAN);
(*------------------------------------*)
PROCEDURE GTT (t0, t1 : OCT.Struct; varpar : BOOLEAN);
VAR t : OCT.Struct; xt, tdes, x1 : OCT.Item;
(*------------------------------------*)
PROCEDURE DeRef (VAR x : OCT.Item);
VAR y, z : OCT.Item;
BEGIN (* DeRef *)
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (x, x.obj)
ELSE
y := x; y.obj := NIL; y.typ := OCT.ptrtyp; OCC.GetAReg (x, x.obj);
IF OCS.pragma [OCS.nilChk] THEN
OCC.GetDReg (z, NIL); OCC.Move (L, y, z); (* MOVE.L x,Dn *)
OCC.TrapCC (OCC.NilCheck, OCC.EQ);
OCC.Move (L, z, x); OCI.Unload (z) (* MOVEA.L Dn, An *)
ELSE
OCC.Move (L, y, x) (* MOVEA.L x, An *)
END
END;
x.mode := RegI; x.a1 := 0; x.a2 := 0; x.rdOnly := FALSE
END DeRef;
BEGIN (* GTT *)
IF t0 # t1 THEN
t := t1;
IF t0.form = Record THEN
REPEAT t := t.BaseTyp UNTIL (t = NIL) OR (t = t0);
END;
IF t # NIL THEN
x.typ := y.typ;
IF OCS.pragma [OCS.typeChk] OR test THEN
IF varpar THEN
xt := x; xt.mode := Ind; xt.a0 := x.a0 + 4; xt.obj := NIL
ELSE
x1 := x; DeRef (x1); x1.a1 := -4; OCC.GetAReg (xt, NIL);
OCC.Move (L, x1, xt); OCI.Unload (x1); xt.mode := RegI
END;
xt.a1 := (t1.n + 1) * 4; xt.typ := OCT.tagtyp;
tdes.mode := Con; tdes.a0 := 0; tdes.a1 := 0;
tdes.label := t1.label; tdes.typ := OCT.tagtyp;
OCI.Adr (tdes); OCI.CMP (L, tdes, xt); (* CMP.L tdes,<xt> *)
OCI.Unload (tdes); OCI.Unload (xt);
IF ~test THEN OCC.TrapCC (OCC.TypeCheck, OCC.NE)
ELSE setCC (x, OCC.EQ)
END
END
ELSE OCS.Mark (85); IF test THEN x.typ := OCT.booltyp END
END
ELSIF test THEN setCC (x, OCC.T)
END
END GTT;
BEGIN (* TypTest *)
IF (x.typ.form = Pointer) & (x.typ.sysflg = OberonFlag) THEN
IF (y.typ.form = Pointer) & (y.typ.sysflg = OberonFlag) THEN
GTT (x.typ.BaseTyp, y.typ.BaseTyp, FALSE)
ELSE OCS.Mark (86)
END
ELSIF x.typ.form = PtrTyp THEN
IF
(y.typ.form = Pointer) & (y.typ.sysflg = OberonFlag)
& (y.typ.BaseTyp # NIL) & (y.typ.BaseTyp.form # DynArr)
THEN
GTT (x.typ, y.typ.BaseTyp, FALSE)
ELSE OCS.Mark (86)
END
ELSIF
(x.typ.form = Record) & (x.typ.sysflg = OberonFlag)
& (x.mode = Ind) & (x.obj # NIL) & (x.obj # OCC.wasderef)
& (y.typ.form = Record) & (y.typ.sysflg = OberonFlag)
THEN
GTT (x.typ, y.typ, TRUE)
ELSE OCS.Mark (87)
END
END TypTest;
(*------------------------------------*)
PROCEDURE In * (VAR lhs, rhs : OCT.Item);
VAR f, g : INTEGER; L0 : LONGINT; bnd, br : OCT.Item;
BEGIN (* In *)
f := lhs.typ.form; g := rhs.typ.form;
IF (f IN intSet) & (g IN setSet) THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
IF (lhs.a0 >= 0) & (lhs.a0 < 32) THEN
IF lhs.a0 IN SYS.VAL (SET, rhs.a0) THEN setCC (lhs, OCC.T)
ELSE setCC (lhs, OCC.F)
END
ELSE
OCS.Mark (91); setCC (lhs, OCC.F)
END
ELSIF lhs.mode = Con THEN
IF
(lhs.a0 < 0)
OR ((g = BSet) & (lhs.a0 > 7))
OR ((g = WSet) & (lhs.a0 > 15))
OR ((g = Set) & (lhs.a0 > 31))
THEN
OCS.Mark (91); setCC (lhs, OCC.F)
ELSE
OCI.Load (rhs); OCC.Bit (OCC.BTST, lhs, rhs);
OCI.Unload (rhs); setCC (lhs, OCC.NE)
END; (* ELSE *)
ELSE
IF rhs.mode = Con THEN rhs.typ := OCT.settyp; g := Set END;
OCI.Load (lhs);
IF OCS.pragma [OCS.rangeChk] THEN
IF lhs.typ.form = SInt THEN OCI.EXT (W, lhs.a0) END;
bnd.mode := Con;
IF g = BSet THEN bnd.a0 := 7
ELSIF g = WSet THEN bnd.a0 := 15
ELSE bnd.a0 := 31
END;
IF lhs.typ.form = LInt THEN
bnd.typ := OCT.linttyp;
OCC.PutF1 (OCC.TST, L, lhs); (* TST.L <lhs> *)
L0 := OCC.pc; OCC.PutWord (6B00H); (* BMI.S 1$ *)
cmp (lhs, bnd, FALSE); (* CMP #<bnd>,<lhs>*)
OCC.TrapLink (OCC.IndexCheck, OCC.GT, L0);
(* BLE.S 2$ *)
(* 1$ TRAP #IndexCheck *)
ELSE (* 2$ *)
bnd.typ := OCT.inttyp; OCC.PutCHK (bnd, lhs.a0)
END
END;
OCI.Load (rhs); OCC.Bit (OCC.BTST, lhs, rhs);
OCI.Unload (lhs); OCI.Unload (rhs); setCC (lhs, OCC.NE)
END
ELSE OCS.Mark (92); setCC (lhs, OCC.F)
END
END In;
(*------------------------------------*)
PROCEDURE Set0 * (VAR x, y : OCT.Item);
VAR one : LONGINT;
BEGIN (* Set0 *)
x.mode := Reg; x.a0 := D0; x.typ := OCT.settyp;
IF y.typ.form IN intSet THEN
IF y.mode = Con THEN
x.mode := Con;
IF (0 <= y.a0) & (y.a0 < 32) THEN
one := 1; x.a0 := SYS.LSH (one, y.a0); SetSetType (x)
ELSE
OCS.Mark (202)
END
ELSE
x.mode := Con; x.a0 := 1; OCI.Load (x); OCI.Load (y);
OCC.Shift (OCC.LSL, L, y, x); OCI.Unload (y)
END
ELSE OCS.Mark (93)
END
END Set0;
(*------------------------------------*)
PROCEDURE Set1 * (VAR x, y, z : OCT.Item);
VAR s : LONGINT;
BEGIN (* Set1 *)
x.mode := Reg; x.a0 := D0; x.typ := OCT.settyp;
IF
(y.typ.form IN intSet) & (z.typ.form IN intSet)
THEN
IF y.mode = Con THEN
IF (0 <= y.a0) & (y.a0 < 32) THEN
y.typ := OCT.settyp; s := -1; y.a0 := SYS.LSH (s, y.a0);
IF z.mode = Con THEN
x.mode := Con;
IF (y.a0 <= z.a0) & (z.a0 < 32) THEN
s := -2; x.a0 := y.a0 - SYS.LSH (s, z.a0); SetSetType (x)
ELSE
OCS.Mark (202); x.a0 := 0
END
ELSIF y.a0 = -1 THEN
x.mode := Con; x.a0 := -2; OCI.Load (x); OCI.Load (z);
OCC.Shift (OCC.LSL, L, z, x); OCC.PutF1 (OCC.NOT, L, x);
OCC.FreeReg (z)
ELSE
x := y; y.mode := Con; y.a0 := -2; OCI.Load (y); OCI.Load (z);
OCC.Shift (OCC.LSL, L, z, y); OCC.FreeReg (z);
OCC.PutF1 (OCC.NOT, L, y); OCI.Load (x);
OCC.PutF5 (OCC.AND, L, y, x); OCC.FreeReg (y)
END
ELSE
OCS.Mark (202)
END
ELSE
x.mode := Con; x.a0 := -1; OCI.Load (x); OCI.Load (y);
OCC.Shift (OCC.LSL, L, y, x); OCC.FreeReg (y);
y.mode := Con; y.typ := NIL;
IF z.mode = Con THEN
IF (0 <= z.a0) & (z.a0 < 32) THEN
s := -2;
y.a0 := SYS.VAL (LONGINT, allSet - SYS.VAL (SET, SYS.LSH(s, z.a0)));
OCC.PutF6 (OCC.ANDI, L, y, x)
ELSE
OCS.Mark (202)
END
ELSE
y.a0 := -2; OCI.Load (y); OCI.Load (z);
OCC.Shift (OCC.LSL, L, z, y); OCC.FreeReg (z);
OCC.PutF1 (OCC.NOT, L, y); OCC.PutF5 (OCC.AND, L, y, x);
OCC.FreeReg (y)
END
END (* ELSE *)
ELSE
OCS.Mark (93)
END
END Set1;
(*------------------------------------*)
PROCEDURE MOp * (op : INTEGER; VAR x : OCT.Item);
VAR f : INTEGER; a, opcode : LONGINT; y : OCT.Item; freeY : BOOLEAN;
BEGIN (* MOp *)
f := x.typ.form;
CASE op OF
and :
IF (x.typ.form = Bool) & (x.mode = Con) THEN
IF x.a0 = 0 THEN setCC (x, OCC.F) ELSE setCC (x, OCC.T) END
END;
IF x.mode = Coc THEN
IF x.a0 # OCC.T THEN
IF x.a0 = OCC.F THEN opcode := OCC.BRA
ELSE opcode := OCC.Bcc + (OCC.invertedCC (x.a0) * 100H)
END;
OCC.PutWord (opcode); OCC.PutWord (x.a2); x.a2 := OCC.pc - 2
END;
OCC.FixLink (x.a1)
ELSIF x.typ.form = Bool THEN
test (x); OCC.PutWord (OCC.BEQ); OCC.PutWord (x.a2);
x.a2 := OCC.pc - 2; OCC.FixLink (x.a1)
ELSE
OCS.Mark (94); x.mode := Con; x.typ := OCT.booltyp; x.a0 := 0
END
|
plus :
IF ~(f IN intSet + realSet) THEN OCS.Mark (96) END
|
minus :
IF f IN intSet THEN
IF x.mode = Con THEN x.a0 := -x.a0; SetIntType (x)
ELSE OCI.Load (x); OCC.PutF1 (OCC.NEG, x.typ.size, x)
END
ELSIF f IN realSet THEN
IF x.mode = Con THEN
x.a0 := SYS.VAL (LONGINT, - SYS.VAL (REAL, x.a0))
ELSE
NegReal (x)
END
ELSIF f IN setSet THEN
IF x.mode = Con THEN
x.a0 := SYS.VAL (LONGINT, allSet - SYS.VAL (SET, x.a0))
ELSE
OCI.Load (x); OCC.PutF1 (OCC.NOT, x.typ.size, x)
END
ELSE
OCS.Mark (97)
END
|
or :
IF (x.typ.form = Bool) & (x.mode = Con) THEN
IF x.a0 = 0 THEN setCC (x, OCC.F) ELSE setCC (x, OCC.T) END
END; (* IF *)
IF x.mode = Coc THEN
IF x.a0 # OCC.F THEN
IF x.a0 = OCC.T THEN opcode := OCC.BRA
ELSE opcode := OCC.Bcc + (x.a0 * 100H)
END;
OCC.PutWord (opcode); OCC.PutWord (x.a1);
x.a1 := OCC.pc - 2
END;
OCC.FixLink (x.a2)
ELSIF x.typ.form = Bool THEN
test (x); OCC.PutWord (OCC.BNE); OCC.PutWord (x.a1);
x.a1 := OCC.pc - 2; OCC.FixLink (x.a2)
ELSE
OCS.Mark (94); x.mode := Con; x.typ := OCT.booltyp; x.a0 := 1
END
|
eql .. geq : (* relations *)
IF x.mode = Coc THEN loadB (x) END
|
not :
IF x.typ.form = Bool THEN
IF x.mode = Con THEN
IF x.a0 = 0 THEN x.a0 := 1 ELSE x.a0 := 0 END
ELSIF x.mode = Coc THEN
x.a0 := OCC.invertedCC (x.a0); a := x.a1; x.a1 := x.a2;
x.a2 := a
ELSE
y := x;
OCC.PutF1 (OCC.TST, B, y); setCC (x, OCC.EQ);
END
ELSE
OCS.Mark (98)
END
|
ELSE
OCS.Mark (1010); OCS.Mark (op)
END; (* CASE op *)
END MOp;
(*------------------------------------*)
PROCEDURE CheckOverflow (op : INTEGER; VAR lhs, rhs : OCT.Item);
CONST min = OCM.MinLInt; max = OCM.MaxLInt;
BEGIN (* CheckOverflow *)
CASE op OF
times :
IF lhs.a0 < 0 THEN
IF (rhs.a0 < 0) & (lhs.a0 < max DIV rhs.a0) THEN
OCS.Mark (109); rhs.a0 := -1
ELSIF (rhs.a0 > 0) & (lhs.a0 < min DIV rhs.a0) THEN
OCS.Mark (109); rhs.a0 := 1
END
ELSE
IF (rhs.a0 < 0) & (lhs.a0 > min DIV rhs.a0) THEN
OCS.Mark (109); rhs.a0 := -1
ELSIF (rhs.a0 > 0) & (lhs.a0 > max DIV rhs.a0) THEN
OCS.Mark (109); rhs.a0 := 1
END
END
|
plus :
IF lhs.a0 < 0 THEN
IF (rhs.a0 < 0) & (lhs.a0 < min - rhs.a0) THEN
OCS.Mark (109); rhs.a0 := 0
END
ELSE
IF (rhs.a0 > 0) & (lhs.a0 > max - rhs.a0) THEN
OCS.Mark (109); rhs.a0 := 0
END
END
|
minus :
IF lhs.a0 < 0 THEN
IF (rhs.a0 > 0) & (lhs.a0 < min + rhs.a0) THEN
OCS.Mark (109); rhs.a0 := 0
END
ELSE
IF (rhs.a0 < 0) & (lhs.a0 > max + rhs.a0) THEN
OCS.Mark (109); rhs.a0 := 0
END
END
|
ELSE
OCS.Mark (1011); OCS.Mark (op)
END; (* CASE op *)
END CheckOverflow;
(*------------------------------------*)
PROCEDURE Op * (op : INTEGER; VAR lhs, rhs : OCT.Item; freeRegs : BOOLEAN);
CONST
eqSet = { Undef, Char .. LInt, BSet .. Set,
NilTyp, PtrTyp .. ProcTyp, TagTyp };
nilSet = { Pointer, PtrTyp, AdrTyp, BPtrTyp, ProcTyp, TagTyp };
VAR f, g : INTEGER; p, q, r : OCT.Struct; size : LONGINT;
(*------------------------------------*)
PROCEDURE strings () : BOOLEAN;
BEGIN (* strings *)
RETURN
((((f = Array) OR (f = DynArr)) & (lhs.typ.BaseTyp.form = Char))
OR (f = String))
& ((((g = Array) OR (g = DynArr)) & (rhs.typ.BaseTyp.form = Char))
OR (g = String))
END strings;
(*------------------------------------*)
PROCEDURE CompStrings (cc : INTEGER; testNul : BOOLEAN);
VAR br, len, ch : OCT.Item; L0, L1 : LONGINT; d : OCT.Desc;
BEGIN (* CompStrings *)
IF (g = String) & (rhs.a1 = 1) THEN
IF (f = String) & (lhs.a1 <= 2) THEN
OCC.AllocStringFromChar (lhs)
END;
IF cc = OCC.CS THEN setCC (lhs, OCC.F)
ELSIF cc = OCC.CC THEN setCC (lhs, OCC.T)
ELSE
IF (f = DynArr) & (lhs.mode = Var) THEN lhs.mode := Ind END;
OCC.PutF1 (OCC.TST, B, lhs); (* TST.B <lhs> *)
OCI.Unload (lhs); setCC (lhs, cc)
END
ELSIF (f = String) & (lhs.a1 = 1) THEN
IF cc = OCC.CS THEN cc := OCC.HI
ELSIF cc = OCC.HI THEN cc := OCC.CS
ELSIF cc = OCC.CC THEN cc := OCC.LS
ELSIF cc = OCC.LS THEN cc := OCC.CC
END;
IF cc = OCC.CS THEN setCC (lhs, OCC.F)
ELSIF cc = OCC.CC THEN setCC (lhs, OCC.T)
ELSE
IF (g = DynArr) & (rhs.mode = Var) THEN rhs.mode := Ind END;
OCC.PutF1 (OCC.TST, B, rhs); (* TST.B <rhs> *)
setCC (lhs, cc)
END
ELSE
IF f = String THEN
IF lhs.a1 = 2 THEN OCC.AllocStringFromChar (lhs) END;
len.mode := Con; len.a0 := lhs.a1 - 1; len.typ := OCT.inttyp
ELSIF f = DynArr THEN
OCI.DescItem (len, lhs.desc, lhs.typ.adr)
ELSE
len.mode := Con; len.a0 := lhs.typ.n - 1; len.typ := OCT.inttyp
END;
IF (g = String) & (rhs.a1 = 2) THEN OCC.AllocStringFromChar (rhs) END;
OCI.Load (len); (* MOVE.Z <len>,Dc *)
OCI.LoadAdr (lhs); lhs.mode := Pop; (* LEA <lhs>,Aa *)
OCI.LoadAdr (rhs); rhs.mode := Pop; (* LEA <rhs>,Ab *)
OCC.ForgetReg (lhs.a0); OCC.ForgetReg (rhs.a0);
OCC.GetDReg (ch, NIL); OCC.Move (B, lhs, ch);(* MOVE.B (Aa)+,Dd *)
OCC.PutF5 (OCC.CMP, B, rhs, ch); (* CMP.B (Ab)+,Dd *)
L0 := OCC.pc; OCC.PutWord (6600H); (* 1$ BNE.S 2$ *)
OCC.PutF1 (OCC.TST, B, ch); (* TST.B Dd *)
L1 := OCC.pc; OCC.PutWord (6700H); (* BEQ.S 2$ *)
OCC.PutWord (OCC.DBF + len.a0);
OCC.PutWord (-12); (* DBF.W Dc,1$ *)
IF testNul THEN
lhs.mode := RegI; lhs.a1 := 0;
OCC.PutF1 (OCC.TST, B, lhs); (* TST.B (Aa) *)
END; (* 2$ *)
OCC.PatchWord (L0, OCC.pc - L0 - 2);
OCC.PatchWord (L1, OCC.pc - L1 - 2);
OCI.Unload (lhs); OCI.Unload (len); OCI.Unload (ch);
setCC (lhs, cc)
END
END CompStrings;
(*------------------------------------*)
PROCEDURE CompBool (cc : LONGINT);
VAR result : BOOLEAN; swap : OCT.Item;
BEGIN (* CompBool *)
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
IF cc = OCC.EQ THEN result := (lhs.a0 = rhs.a0)
ELSE result := (lhs.a0 # rhs.a0)
END;
IF result THEN setCC (lhs, OCC.T)
ELSE setCC (lhs, OCC.F)
END;
ELSE
IF lhs.mode = Con THEN (* swap operands *)
swap := rhs; rhs := lhs; lhs := swap
END;
IF rhs.mode = Coc THEN loadB (rhs)
ELSIF (rhs.mode = Con) & (rhs.a0 # 0) THEN
(* Comparing with TRUE.
** Invert the CC so that a TST can be used.
*)
cc := OCC.invertedCC (cc); rhs.a0 := 0
END;
cmp (lhs, rhs, freeRegs); setCC (lhs, cc)
END; (* IF *)
END CompBool;
BEGIN (* Op *)
IF lhs.typ # rhs.typ THEN
f := lhs.typ.form; g := rhs.typ.form;
CASE f OF
Undef :
|
SInt :
IF g = Int THEN ConvertInts (lhs, rhs.typ)
ELSIF g = LInt THEN ConvertInts (lhs, rhs.typ)
ELSIF g = Real THEN ConvertReals (lhs, rhs.typ)
ELSIF g = LReal THEN ConvertReals (lhs, rhs.typ)
ELSE OCS.Mark (100)
END
|
Int :
IF g = SInt THEN ConvertInts (rhs, lhs.typ)
ELSIF g = LInt THEN ConvertInts (lhs, rhs.typ)
ELSIF g = Real THEN ConvertReals (lhs, rhs.typ)
ELSIF g = LReal THEN ConvertReals (lhs, rhs.typ)
ELSE OCS.Mark (100)
END
|
LInt :
IF g = SInt THEN ConvertInts (rhs, lhs.typ)
ELSIF g = Int THEN ConvertInts (rhs, lhs.typ)
ELSIF g = Real THEN ConvertReals (lhs, rhs.typ)
ELSIF g = LReal THEN ConvertReals (lhs, rhs.typ)
ELSE OCS.Mark (100)
END
|
Real :
IF g IN intSet THEN ConvertReals (rhs, lhs.typ)
ELSIF g = LReal THEN ConvertReals (lhs, rhs.typ)
ELSE OCS.Mark (100)
END
|
LReal :
IF g IN intSet THEN ConvertReals (rhs, lhs.typ)
ELSIF g = Real THEN ConvertReals (rhs, lhs.typ)
ELSE OCS.Mark (100)
END
|
BSet, WSet, Set :
IF g IN setSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
IF g >= f THEN lhs.typ := rhs.typ
ELSE rhs.typ := lhs.typ
END
ELSIF lhs.mode = Con THEN
SetSetType (lhs);
IF g >= lhs.typ.form THEN lhs.typ := rhs.typ
ELSE OCS.Mark (100)
END
ELSIF rhs.mode = Con THEN
SetSetType (rhs);
IF f >= rhs.typ.form THEN rhs.typ := lhs.typ
ELSE OCS.Mark (100)
END
ELSE OCS.Mark (100)
END
ELSE OCS.Mark (100)
END
|
NilTyp :
IF ~(g IN nilSet) THEN OCS.Mark (100) END
|
Pointer :
IF (g = Pointer) & (OCT.Tagged (lhs.typ) = OCT.Tagged (rhs.typ)) THEN
p := lhs.typ.BaseTyp; q := rhs.typ.BaseTyp;
IF (p.form = Record) & (q.form = Record) THEN
IF p.n < q.n THEN r := p; p := q; q := r END;
WHILE (p # q) & (p # NIL) DO p := p.BaseTyp END;
IF p = NIL THEN OCS.Mark (100) END
ELSE
OCS.Mark (100)
END
ELSIF OCT.Address (lhs.typ) THEN
IF ~(g IN {AdrTyp, NilTyp}) THEN OCS.Mark (100) END
ELSIF g # NilTyp THEN
OCS.Mark (100)
END
|
AdrTyp :
IF ~OCT.Address (rhs.typ) THEN OCS.Mark (100) END
|
PtrTyp, BPtrTyp, ProcTyp, TagTyp :
IF g # NilTyp THEN OCS.Mark (100) END
|
Char :
IF (g = String) & (rhs.a1 <= 2) THEN
rhs.a0 := rhs.a2; rhs.typ := OCT.chartyp; g := Char
ELSE OCS.Mark (100)
END
|
String :
IF (g = Char) & (lhs.a1 <= 2) THEN
lhs.a0 := lhs.a2; lhs.typ := OCT.chartyp; f := Char
ELSIF (g = String) & (lhs.a1 <= 2) & (rhs.a1 <= 2) THEN
lhs.a0 := lhs.a2; lhs.typ := OCT.chartyp; f := Char;
rhs.a0 := rhs.a2; rhs.typ := OCT.chartyp; g := Char
END
|
Byte, Bool, NoTyp, Record, Word, Longword :
OCS.Mark (100);
|
Array, DynArr :
|
ELSE
OCS.Mark (1012); OCS.Mark (f)
END; (* CASE f *)
END; (* IF *)
f := lhs.typ.form; g := rhs.typ.form; size := lhs.typ.size;
IF lhs.mode = RList THEN (* lhs is a function procedure result *)
IF f # Pointer THEN OCS.Mark (956) END;
OCC.FreeReg (lhs); lhs.mode := Reg; lhs.a0 := D0;
OCC.ReserveReg (D0, NIL)
END;
IF rhs.mode = RList THEN (* rhs is a function procedure result *)
IF f # Pointer THEN OCS.Mark (956) END;
OCC.FreeReg (rhs); rhs.mode := Reg; rhs.a0 := D0;
OCC.ReserveReg (D0, NIL)
END;
CASE op OF
times :
IF f IN intSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
CheckOverflow (times, lhs, rhs);
lhs.a0 := lhs.a0 * rhs.a0; SetIntType (lhs)
ELSE
MultiplyInts (lhs, rhs, size, freeRegs)
END
ELSIF f IN realSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT,
SYS.VAL (REAL, lhs.a0) * SYS.VAL (REAL, rhs.a0))
ELSE
RealMath (times, lhs, rhs)
END
ELSIF f IN setSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT, SYS.VAL (SET, lhs.a0) * SYS.VAL (SET, rhs.a0))
ELSIF lhs.mode = Con THEN
OCI.Load (rhs); OCC.PutF6 (OCC.ANDI, size, lhs, rhs); lhs := rhs;
rhs.mode := Undef
ELSE
OCI.Load (lhs); OCC.PutF5 (OCC.AND, size, rhs, lhs)
END
ELSIF f # Undef THEN OCS.Mark (101)
END
|
slash :
IF f IN (realSet + intSet) THEN
IF f IN intSet THEN
ConvertReals (lhs, OCT.realtyp); ConvertReals (rhs, OCT.realtyp)
END;
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT,
SYS.VAL (REAL, lhs.a0) / SYS.VAL (REAL, rhs.a0))
ELSE
RealMath (slash, lhs, rhs)
END
ELSIF f IN setSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT, SYS.VAL (SET, lhs.a0) / SYS.VAL (SET, rhs.a0))
ELSIF rhs.mode = Con THEN
OCI.Load (lhs); OCC.PutF6 (OCC.EORI, size, rhs, lhs)
ELSIF lhs.mode = Con THEN
OCI.Load (rhs); OCC.PutF6 (OCC.EORI, size, lhs, rhs);
lhs := rhs; rhs.mode := Undef
ELSE
OCI.Load (lhs); OCI.Load (rhs);
OCC.PutF5 (OCC.EOR, size, rhs, lhs)
END
ELSIF f # Undef THEN OCS.Mark (102)
END
|
div :
IF f IN intSet THEN
IF (rhs.mode = Con) & (rhs.a0 = 0) THEN
OCS.Mark (205); rhs.a0 := 1
END;
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 := lhs.a0 DIV rhs.a0; SetIntType (lhs);
ELSE
DivideInts (lhs, rhs, size, freeRegs);
END
ELSIF f # Undef THEN OCS.Mark (103)
END
|
mod :
IF f IN intSet THEN
IF (rhs.mode = Con) & (rhs.a0 = 0) THEN
OCS.Mark (205); rhs.a0 := 1
END;
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 := lhs.a0 MOD rhs.a0; lhs.typ := rhs.typ
ELSE
ModulusInts (lhs, rhs, size, freeRegs)
END
ELSIF f # Undef THEN OCS.Mark (104)
END
|
and :
IF rhs.mode # Coc THEN
IF rhs.mode = Con THEN
IF rhs.a0 = 1 THEN setCC (rhs, OCC.T) ELSE setCC (rhs, OCC.F) END
ELSIF rhs.mode <= Reg THEN test (rhs);
ELSE OCS.Mark (94); setCC (rhs, OCC.EQ)
END
END;
IF lhs.mode = Con THEN
IF lhs.a0 = 0 THEN
OCC.FixLink (rhs.a1); OCC.FixLink (rhs.a2); setCC (rhs, OCC.F)
END;
setCC (lhs, OCC.EQ)
END;
IF rhs.a2 # 0 THEN lhs.a2 := OCC.MergedLinks (lhs.a2, rhs.a2)
END;
lhs.a0 := rhs.a0; lhs.a1 := rhs.a1
|
plus :
IF f IN intSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
CheckOverflow (plus, lhs, rhs); INC (lhs.a0, rhs.a0);
SetIntType (lhs)
ELSE
OCI.Load (lhs); OCC.PutF5 (OCC.ADD, size, rhs, lhs);
IF OCS.pragma [OCS.ovflChk] THEN OCC.Trap (OCC.OverflowCheck) END
END
ELSIF f IN realSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT,
SYS.VAL (REAL, lhs.a0) + SYS.VAL (REAL, rhs.a0))
ELSE
RealMath (plus, lhs, rhs)
END
ELSIF f IN setSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT, SYS.VAL (SET, lhs.a0) + SYS.VAL (SET, rhs.a0))
ELSIF lhs.mode = Con THEN
OCI.Load (rhs); OCC.PutF6 (OCC.ORI, size, lhs, rhs); lhs := rhs;
rhs.mode := Undef
ELSE
OCI.Load (lhs); OCC.PutF5 (OCC.iOR, size, rhs, lhs)
END
ELSIF f # Undef THEN OCS.Mark (105)
END
|
minus :
IF f IN intSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
CheckOverflow (minus, lhs, rhs); DEC (lhs.a0, rhs.a0);
SetIntType (lhs)
ELSE
OCI.Load (lhs); OCC.PutF5 (OCC.SUB, size, rhs, lhs);
IF OCS.pragma [OCS.ovflChk] THEN OCC.Trap (OCC.OverflowCheck) END
END
ELSIF f IN realSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT,
SYS.VAL (REAL, lhs.a0) - SYS.VAL (REAL, rhs.a0))
ELSE
RealMath (minus, lhs, rhs)
END
ELSIF f IN setSet THEN
IF (lhs.mode = Con) & (rhs.mode = Con) THEN
lhs.a0 :=
SYS.VAL (LONGINT, SYS.VAL (SET, lhs.a0) - SYS.VAL (SET, rhs.a0));
ELSIF rhs.mode = Con THEN
rhs.a0 := SYS.VAL (LONGINT, allSet - SYS.VAL (SET, rhs.a0));
OCI.Load (lhs); OCC.PutF6 (OCC.ANDI, size, rhs, lhs)
ELSIF lhs.mode = Con THEN
OCI.Load (rhs); OCC.PutF1 (OCC.NOT, size, rhs);
IF ~(lhs.a0 = -1) THEN OCC.PutF6 (OCC.ANDI, size, lhs, rhs) END;
lhs := rhs; rhs.mode := Undef
ELSE
OCI.Load (lhs); OCI.Load (rhs); OCC.PutF1 (OCC.NOT, size, rhs);
OCC.PutF5 (OCC.AND, size, rhs, lhs)
END
ELSIF f # Undef THEN OCS.Mark (106)
END
|
or :
IF rhs.mode # Coc THEN
IF rhs.mode = Con THEN
IF rhs.a0 = 1 THEN setCC (rhs, OCC.T) ELSE setCC (rhs, OCC.F) END
ELSIF rhs.mode <= Reg THEN test (rhs)
ELSE OCS.Mark (95); setCC (rhs, OCC.EQ)
END
END;
IF lhs.mode = Con THEN
IF lhs.a0 = 1 THEN
OCC.FixLink (rhs.a1); OCC.FixLink (rhs.a2); setCC (rhs, OCC.T)
END;
setCC (lhs, OCC.EQ)
END;
IF rhs.a1 # 0 THEN lhs.a1 := OCC.MergedLinks (lhs.a1, rhs.a1) END;
lhs.a0 := rhs.a0; lhs.a2 := rhs.a2
|
eql :
IF f IN eqSet THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.EQ)
ELSIF f IN realSet THEN CmpReals (lhs, rhs); setCC (lhs, OCC.EQ)
ELSIF f = Bool THEN CompBool (OCC.EQ)
ELSIF strings () THEN CompStrings (OCC.EQ, TRUE)
ELSE OCS.Mark (107)
END
|
neq :
IF f IN eqSet THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.NE)
ELSIF f IN realSet THEN CmpReals (lhs, rhs); setCC (lhs, OCC.NE)
ELSIF f = Bool THEN CompBool (OCC.NE)
ELSIF strings () THEN CompStrings (OCC.NE, TRUE)
ELSE OCS.Mark (107)
END
|
lss :
IF f IN intSet THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.LT)
ELSIF f = Char THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.CS)
ELSIF f IN realSet THEN CmpReals (lhs, rhs); setCC (lhs, OCC.LT)
ELSIF strings () THEN CompStrings (OCC.CS, FALSE)
ELSE OCS.Mark (108)
END
|
leq :
IF f IN intSet THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.LE)
ELSIF f = Char THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.LS)
ELSIF f IN realSet THEN CmpReals (lhs, rhs); setCC (lhs, OCC.LE)
ELSIF strings () THEN CompStrings (OCC.LS, TRUE)
ELSE OCS.Mark (108)
END
|
gtr :
IF f IN intSet THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.GT)
ELSIF f = Char THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.HI)
ELSIF f IN realSet THEN CmpReals (lhs, rhs); setCC (lhs, OCC.GT)
ELSIF strings () THEN CompStrings (OCC.HI, TRUE)
ELSE OCS.Mark (108)
END
|
geq :
IF f IN intSet THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.GE)
ELSIF f = Char THEN cmp (lhs, rhs, freeRegs); setCC (lhs, OCC.CC)
ELSIF f IN realSet THEN CmpReals (lhs, rhs); setCC (lhs, OCC.GE)
ELSIF strings () THEN CompStrings (OCC.CC, FALSE)
ELSE OCS.Mark (108)
END
|
ELSE
OCS.Mark (1013); OCS.Mark (op)
END; (* CASE op *)
IF freeRegs THEN OCI.Unload (rhs) END;
END Op;
END OCE.
(***************************************************************************
$Log: OCE.mod $
Revision 5.22 1995/07/02 16:52:04 fjc
*** empty log message ***
Revision 5.21 1995/07/02 16:50:44 fjc
- Fixed pointer to open array bug in DeRef().
Revision 5.20 1995/06/29 19:10:45 fjc
- Removed code that was second-guessing the garbage collector
Revision 5.19 1995/06/15 18:13:29 fjc
- Didn't free all registers when processing type tests.
Revision 5.18 1995/06/02 18:40:02 fjc
- Now uses OCI.CMP.
Revision 5.17 1995/05/13 23:07:13 fjc
- Changed INTEGER to LONGINT where necessary.
- Now allows floating point constant expressions.
Revision 5.16 1995/04/23 17:45:49 fjc
- Merging 5.26 & 5.27
Revision 5.13 1995/03/23 18:18:18 fjc
- More work on remembering registers in Index(), Field() and
DeRef().
Revision 5.12 1995/03/13 11:31:47 fjc
- Reverted to forced loading of Ind objects in Field() and
Index().
Revision 5.11 1995/03/09 19:09:45 fjc
- Incorporated changes from 5.22.
Revision 5.10 1995/02/27 17:02:54 fjc
- Removed tracing code.
- Modified to use new register handling procedures.
Revision 5.9.1.1 1995/03/08 19:01:25 fjc
- OC 5.22
Revision 5.9 1995/02/21 11:56:58 fjc
- OC 5.21
Revision 5.8 1995/01/26 00:17:17 fjc
- Release 1.5
Revision 5.7 1995/01/03 21:19:32 fjc
- Changed OCG to OCM.
Revision 5.6 1994/12/16 17:29:27 fjc
- Changed Symbol to Label.
- Minor modifications to type tests.
Revision 5.5 1994/10/23 16:10:52 fjc
- All calls to the RTS now made through OCC.CallKernel().
Revision 5.4 1994/09/25 17:49:43 fjc
- Changed to reflect new object modes and system flags.
Revision 5.3 1994/09/15 10:33:02 fjc
- Replaced switches with pragmas.
- Fixed register reservation bug in DeRef when NIL checking.
was on.
Revision 5.2 1994/09/08 10:49:29 fjc
- Changed to use pragmas/options.
Revision 5.1 1994/09/03 19:29:08 fjc
- Bumped version number
***************************************************************************)